import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { EffectComposer } from 'three/examples/jsm/postprocessing/EffectComposer.js'
import { RenderPass } from 'three/examples/jsm/postprocessing/RenderPass.js'
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js'
import { ShaderPass } from 'three/examples/jsm/postprocessing/ShaderPass.js'
import { FXAAShader } from 'three/examples/jsm/shaders/FXAAShader.js'
// 伽马校正后处理Shader
import {GammaCorrectionShader} from 'three/addons/shaders/GammaCorrectionShader.js';

// 定义全局变量
let composer
let outlinePass



import * as dat from 'dat.gui'


export const threes = {
  data() {
    return {
      baseUrl: 'https://zfatt.oss-cn-beijing.aliyuncs.com/experiment/ctxn/',
      cameras: null,
      scale: 0,
      objectNames: [
        'PaiFengShanHouMianBan_3',
        'PaiFengShan_1',
        'HangChaMoZu',
        'PaiFengShanQianMianBan_1',
        'TanCeQiHouBan',
        'TanCeQiKongZhiBan_3',
        'PaiFengShanGuDingBan_1',
        'SaoMiaoZhenLieQianMianBan_24'
      ],
      //气泡对应名称
      objectText: [
        { name: 'PaiFengShanHouMianBan_3', text: '排风扇后排' },
        { name: 'PaiFengShan_1', text: '排风扇' },
        { name: 'HangChaMoZu', text: '航插模组' },
        { name: 'PaiFengShanQianMianBan_1', text: '排风扇前排' },
        { name: 'TanCeQiHouBan', text: '探测器后板' },
        { name: 'TanCeQiKongZhiBan_3', text: '探测器控制板' },
        { name: 'PaiFengShanGuDingBan_1', text: '排风扇固定板' },
        { name: 'SaoMiaoZhenLieQianMianBan_24', text: '扫描针列前面板' }
      ],

      controls: null,
      playIng: false,
      camera: null,
      scene: null,
      render: null,
      raycaster: null,
      mouse: null,
      objects: [],
      objectFather: null,
      action: null,
      andh: null,
      objectReItem: null,
      dhfiles: ['9TanCeQi.glb'] //''
    }
  },

  created() {},
  mounted() {},
  beforeDestroy() {
    clearTimeout()
    try {
      this.scene.clear()
      this.render.dispose()
      this.render.forceContextLoss()
      this.render.content = null
      // cancelAnimationFrame(animationID) // 去除animationFrame
      const gl = this.render.domElement.getContext('webgl')
      gl && gl.getExtension('WEBGL_lose_context').loseContext()
    } catch (e) {
      console.log(e)
    }
  },

  computed: {
    getPosition() {
      //根据返回的位置信息计算物品提示小标位
      let maincontWidth = this.$el.offsetWidth
      let maincontHeight = this.$el.offsetHeight
      let leftPercentage = ((this.tipPosition.x + 25) / maincontWidth) * 100
      let topPercentage = ((this.tipPosition.y - 30) / maincontHeight) * 100
      return 'left:' + leftPercentage + '%;top:' + topPercentage + '%;'
    }
  },
  methods: {
    //初始化
    init() {
      this.initSence()
      this.raycaster = new THREE.Raycaster() // 设置光线拾取
      this.clock = new THREE.Clock()
      this.mouse = new THREE.Vector2()
    },
    //初始化相机
    initCeremar() {
      let camera = new THREE.PerspectiveCamera(
        75,
        window.innerWidth / window.innerHeight,
        0.1,
        1000
      )
   //   camera.position.set(-0.116, 0.322, 2.632)
      // camera.position.set(-0.116, 0.322, 1.632)
      // camera.lookAt(0, 0, 0)
      this.camera = camera

      this.scene.add(this.camera)
      // this.
    },
    //初始化场景
    initSence() {
      var scene = new THREE.Scene()

      this.scene = scene

      this.initLight()
      this.initCeremar()
      this.initRenderer()

      this.initCotronl()
   
       this.createRenderChannel() // 创建渲染通道
      // this.initGUI()
      this.initFileS(0)
       
    },

    //初始化渲染器
    initRenderer() {
      this.render = new THREE.WebGLRenderer({
        antialias: true,
        alpha: true,
        logarithmicDepthBuffer: true
      })

      this.render.setClearColor(0xaaaaaa)
      this.render.setPixelRatio(window.devicePixelRatio * 2)
      this.render.setSize(window.innerWidth, window.innerHeight)
      this.render.shadowMap.enabled = true
      this.render.shadowMap.type = THREE.PCFSoftShadowMap

      this.render.toneMapping = THREE.ACESFilmicToneMapping
      this.render.toneMappingExposure = 1.6
      // this.render.outputEncoding = THREE.LinearSRGBColorSpace

      this.render.outputColorSpace = THREE.SRGBColorSpace

      this.$el.appendChild(this.render.domElement)
      window.addEventListener('resize', this.onWindowResize) //监听窗口变化

      // 检查 WebGL 上下文是否有效
      const gl = this.render.getContext()
      if (!gl) {
        console.error('Failed to get WebGL context')
      }
    },

    //根据屏幕尺寸变化自适应
    onWindowResize() {
      //浏览器窗口大小改变后重新计算
      this.maincontWidth = this.$el.offsetWidth
      this.maincontHeight = this.$el.offsetHeight
      this.maincontSc = this.maincontWidth / this.maincontHeight
      this.camera.aspect = this.maincontSc
      this.camera.updateProjectionMatrix()
      this.render.setSize(this.maincontWidth, this.maincontHeight)
    }, //鼠标移动6+射线拾取
    //初始化控制器
    initCotronl() {
      this.mouse = new THREE.Vector2() //获取鼠标 位置二维坐标信息
      document.body.addEventListener('mousemove', this.onDocumentMouseMove)
      document.body.addEventListener('mousedown', this.onDocumentMouseDown)
      this.$el.addEventListener('mouseup', this.onDocumentMouseUp)
    }, //初始化物体
   

    destroyOldScene() {
      if (this.objectFather) {
        this.scene.remove(this.objectFather.scene)
        this.objectFather.scene.traverse((child) => {
          if (child.material) {
            child.material.dispose()
          }
          if (child.geometry) {
            child.geometry.dispose()
          }
          child = null
        })

        this.objectFather = null
      }
    },
    //根据步骤渲染物体和动画
    initFileS(index) {
      // const textureCube = new THREE.TextureLoader().load(
      //   'http://zfatt.oss-cn-beijing.aliyuncs.com/experiment/fydw/TaiDeng_C_BaseMap.png'
      // )
      let gltfloader = new GLTFLoader()
      const dracoLoader = new DRACOLoader()
      // dracoLoader.setDecoderPath('/draco/')
      dracoLoader.setDecoderPath(
        'http://zfatt.oss-cn-beijing.aliyuncs.com/threejs/draco/'
      )
      dracoLoader.preload()
      gltfloader.setDRACOLoader(dracoLoader)
      gltfloader.load(this.baseUrl + this.dhfiles[index], (gltf) => {
        this.destroyOldScene()

        // this.objects = []
        gltf.scene.traverse((child) => {
          if (child.isMesh) {
            child.material.metalness = 0.7 // 金属度
            // child.material.roughness = 0.5 // 表面粗糙度
            // child.material.envMap = textureCube // 设置环境贴图
            // child.material.envMapIntensity = 1 // 环境贴图影响程度

            if (this.objectNames.includes(child.name)) {
              //将需要检查到的模型放到objects
              this.objects.push(child)
            }


          }
        })
        const boundingBox = new THREE.Box3().setFromObject(gltf.scene)
        const center = new THREE.Vector3()
        boundingBox.getCenter(center)

        // 将整个模型的中心点对齐到原点
        gltf.scene.position.sub(center)

        // 设置相机角度
        
       
        const  modelSize = boundingBox.getSize(new THREE.Vector3()).length()
          const fov =this.camera.fov * (Math.PI / 180) // 视角转换为弧度
          const cameraDistance = modelSize / (2 * Math.tan(fov / 2)) + 0.2
          const target = boundingBox.getCenter(new THREE.Vector3())

          this.camera.position.set(target.x, target.y, target.z + cameraDistance) // 设置相机位置
        this.camera.lookAt(target)
       
        // this.animate()
        // 设置相机角度
        this.scene.add(gltf.scene)
        this.objectFather = gltf
        this.andh = gltf.animations
        console.log('动画数据', gltf.animations)
        this.render.render(this.scene, this.camera)



         this.initControls() // 初始化控制器
        this.animate()

        this.$emit('loadingfn', false)

        // this.initDragControls(this.Farray) //初始化拖拽控制器
      })
    },

    //初始化灯光
    initLight() {
      const ambientLight = new THREE.AmbientLight(0xffffff, 0.8)
      this.scene.add(ambientLight)
      const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.5)
      directionalLight1.position.set(0.5, 2, 1)
      directionalLight1.position.set(0.05, -0.65, 2.7)
      directionalLight1.castShadow = true
      this.scene.add(directionalLight1)
      const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5)
      directionalLight2.position.set(-11.2, -4.6, -2)
      directionalLight2.castShadow = false
      this.scene.add(directionalLight2)

      const pointLight = new THREE.PointLight(0xffffff, 1, 100)
      pointLight.position.set(5, 5, 5)
      this.scene.add(pointLight)

      // GUI 控制函数
      this.initGUI = function() {
        const gui = new dat.GUI()

        const ambientLightFolder = gui.addFolder('Ambient Light')
        ambientLightFolder.add(ambientLight, 'intensity', 0, 2).name('Intensity')

        const directionalLight1Folder = gui.addFolder('Directional Light 1')
        directionalLight1Folder.add(directionalLight1.position, 'x', -10, 10).name('Position X')
        directionalLight1Folder.add(directionalLight1.position, 'y', -10, 10).name('Position Y')
        directionalLight1Folder.add(directionalLight1.position, 'z', -10, 10).name('Position Z')
        directionalLight1Folder.add(directionalLight1, 'intensity', 0, 2).name('Intensity')

        const directionalLight2Folder = gui.addFolder('Directional Light 2')
        directionalLight2Folder.add(directionalLight2.position, 'x', -10, 10).name('Position X')
        directionalLight2Folder.add(directionalLight2.position, 'y', -10, 10).name('Position Y')
        directionalLight2Folder.add(directionalLight2.position, 'z', -10, 10).name('Position Z')
        directionalLight2Folder.add(directionalLight2, 'intensity', 0, 2).name('Intensity')

        const pointLightFolder = gui.addFolder('Point Light')
        pointLightFolder.add(pointLight.position, 'x', -10, 10).name('Position X')
        pointLightFolder.add(pointLight.position, 'y', -10, 10).name('Position Y')
        pointLightFolder.add(pointLight.position, 'z', -10, 10).name('Position Z')
        pointLightFolder.add(pointLight, 'intensity', 0, 2).name('Intensity')

        gui.open()
      }
    },

    //根据按钮播发动画
    playAction(animationName, realName) {
      console.log('播放了动画名称', animationName, '点击的物体', realName)
      this.playIng = true
      const theMixer = new THREE.AnimationMixer(this.objectFather.scene) //动画的物体
      const clip = THREE.AnimationClip.findByName(
        this.objectFather.animations,
        animationName
      ) //要播放的动画名称
      const action = theMixer.clipAction(clip)
      action.loop = THREE.LoopOnce
      action.clampWhenFinished = true
      action.play()
      this.action = action
      theMixer.addEventListener('finished', () => {
        this.playIng = false
        this.clickItem(realName)
        console.log('动画播放完成，停留在完成状态')
      })
      this.theMixer = theMixer
    },
    //循环渲染
    animate() {
       if (composer) {
        composer.render()
      }
      if (this.animate) { 
       requestAnimationFrame(this.animate)
      }
    
      if (this.theMixer) {
        //动画渲染  3000 控制动画没一帧之间的时长
        this.theMixer.update(this.clock.getDelta())
        // this.clock.getDelta()
      }
      // this.controls.update(); // 更新控制器
      // this.render.render(this.scene, this.camera)
     
    },
    //镜头移动视角切换根据不同的步骤进行操作
    move(position, rotation) {
      if (!this.camera) {
        return
      }
      // this.controls.enabled = false
      this.camera.position.set(position[0], position[1], position[2])
      this.camera.rotation.set(
        rotation[0] * Math.PI,
        rotation[1] * Math.PI,
        rotation[2] * Math.PI
      )
      this.camera.updateProjectionMatrix()
    },
    //按照坐标位置显示指示箭头
    twinklePoint(x, y, z) {
      if (this.sprite) {
        this.sprite.visible = true
        this.sprite.position.set(x, y, z)
        this.spriteTimer = setInterval(() => {
          this.sprite.visible = !this.sprite.visible
        }, 600)
      }
    },
    getTextName(realName) {
      //根据模型名称返回对应汉字
      let textName = ''
      this.objectText.map((item) => {
        if (item.name == realName) {
          textName = item.text
        }
      })
      return textName
    },

    //获取名字
    getRealName(object) {
      //  根据模型返回其父级group的名称，且之后在objects中存在的才会返回名称
      let objectNames = this.objectNames
      if (objectNames.includes(object.name)) {
        return object.name
      } else {
        if (object.parent) {
          return this.getRealName(object.parent)
        } else {
          return ''
        }
      }
    },
    //鼠标移动6+射线拾取
    onDocumentMouseMove(event) {
      let maincontWidth = this.$el.offsetWidth
      let maincontHeight = this.$el.offsetHeight
      this.mouse.x = (event.offsetX / maincontWidth) * 2 - 1
      this.mouse.y = -(event.offsetY / maincontHeight) * 2 + 1
      this.raycaster.setFromCamera(this.mouse, this.camera)

      const intersections = this.raycaster.intersectObjects(this.objects)
      //  console.log('intersections', intersections);

      if (intersections.length > 0) {
        document.body.style.cursor = 'pointer'
      
      } else {
        document.body.style.cursor = 'initial'
      
      }
    },

    //清除指示箭头
    clearPoint() {
      console.log('清楚箭头', this.sprite.visible)
      if (this.sprite) {
        console.log('清楚箭头', this.sprite.visible)
        this.sprite.visible = false
      }
      if (this.spriteTimer) {
        clearInterval(this.spriteTimer)
        this.spriteTimer = null
      }
    },
    //鼠标按下播放动画
    onDocumentMouseDown(event) {
      let maincontWidth = this.$el.offsetWidth
      let maincontHeight = this.$el.offsetHeight
      this.mouse.x = (event.offsetX / maincontWidth) * 2 - 1
      this.mouse.y = -(event.offsetY / maincontHeight) * 2 + 1
      this.raycaster.setFromCamera(this.mouse, this.camera)

      const intersections = this.raycaster.intersectObjects(this.objects)
      if (intersections.length > 0) {
        const intersectedObject = intersections[0].object
  

        // 使用OutlinePass高亮选中对象
        if (outlinePass) {
          outlinePass.selectedObjects = [intersectedObject]
        }
        // 启用拖动
        document.addEventListener('mousemove', this.onDocumentMouseDrag)
        document.addEventListener('mouseup', this.onDocumentMouseUp)

        this.draggedObject = intersectedObject
      } else { 
          if (outlinePass) {
          outlinePass.selectedObjects = []
        }
      }
    },

    onDocumentMouseDrag(event) {
       if (event.buttons == 2) { // 判断是否为右键
        return; // 如果是右键，直接返回
      }
      if (!this.draggedObject) return

      let maincontWidth = this.$el.offsetWidth
      let maincontHeight = this.$el.offsetHeight
      this.mouse.x = (event.offsetX / maincontWidth) * 2 - 1
      this.mouse.y = -(event.offsetY / maincontHeight) * 2 + 1
      this.raycaster.setFromCamera(this.mouse, this.camera)

      const plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0) // 限制平移在垂直于 z 轴的平面上
      const intersection = new THREE.Vector3()
      this.raycaster.ray.intersectPlane(plane, intersection)

      // 更新 x 和 y 坐标，保持 z 坐标不变
      this.draggedObject.position.set(
        intersection.x,
        intersection.y,
        this.draggedObject.position.z
      )
    },

    onDocumentMouseUp() {
      document.removeEventListener('mousemove', this.onDocumentMouseDrag)
      document.removeEventListener('mouseup', this.onDocumentMouseUp)
      this.draggedObject = null
    },
    //根据点击的模型播放动画
    clickAfter(realName) {
      console.log('当前点击的模型', realName)
      this.twinklePoint(-3, -3, -3)
      // 动画还没加载完的情况
      if (!this.andh) {
        console.log('当前没有动画数据')
        if (this.action) {
          this.action.stop()
          this.action.paused = true
        }
        this.action = null
        return
      }
      if (this.playIng) {
        // this.step
        if (!this.playIng) {
          console.log('当前任务还未完成禁止下一个')
        } else {
          return
        }
      }
      let animationName = ''
      if (realName == 'TanCeQi4' && this.taskids == 3) {
        animationName = '2'
        this.playIng = true
      }

      if (!animationName) {
        // console.log('dh')
        console.log('未指定播放动画', animationName, '当前小步骤', this.eritems)
        return
      }

      this.clearPoint()
      this.playAction(animationName, realName)
    },

    // 初始化控制器，支持鼠标旋转、缩放和拖动
    initControls() {
      this.controls = new OrbitControls(this.camera, this.render.domElement)
      this.controls.enableDamping = true // 启用阻尼效果
      this.controls.dampingFactor = 0.05 // 阻尼系数
      this.controls.screenSpacePanning = false // 禁止屏幕平移
      this.controls.minDistance = 0.4 // 最小缩放距离 有时候可能相反
      // this.controls.maxDistance = 0.8 // 最大缩放距离 有时候可能相反
      this.controls.enablePan = false

      // 禁用鼠标左键拖动，仅允许右键旋转
      this.controls.mouseButtons = {
        LEFT: THREE.MOUSE.PAN, // 禁用左键
        MIDDLE: THREE.MOUSE.DOLLY, // 中键缩放
        RIGHT: THREE.MOUSE.ROTATE // 右键旋转
      }
    },

    // 创建渲染通道
    createRenderChannel() {
     
      composer = new EffectComposer(this.render)
      composer.setSize(this.$el.offsetWidth, this.$el.offsetHeight)

      const renderPass = new RenderPass(this.scene, this.camera)
      composer.addPass(renderPass)

      outlinePass = new OutlinePass(
        new THREE.Vector2(this.$el.offsetWidth, this.$el.offsetHeight),
        this.scene,
        this.camera
      )
      outlinePass.pulsePeriod = 2 // 律动
      outlinePass.renderToScreen = true
      outlinePass.edgeGlow = 1 // 边缘微光强度
      outlinePass.edgeStrength = 3
      outlinePass.edgeThickness = 2
      outlinePass.visibleEdgeColor.set('#ff0000')
      outlinePass.hiddenEdgeColor.set('#ff0000')
      outlinePass.selectedObjects = []
      composer.addPass(outlinePass)
 // 创建FXAAShader对象
        let fxaaPass = new ShaderPass(FXAAShader)
        if (!fxaaPass) {
          throw new Error('Failed to initialize FXAAShader')
        }
        fxaaPass.uniforms['resolution'].value.set(
          1 / this.$el.offsetWidth,
          1 / this.$el.offsetHeight
        )
        // 添加FXAA通道到EffectComposer中
        composer.addPass(fxaaPass)
      // 创建伽马校正通道
const gammaPass= new ShaderPass(GammaCorrectionShader);
composer.addPass(gammaPass);

    
    },
    // 动画播放完成
    clickItem(name) {
      console.log('动画播放完成', name)
    }
  }
}
